Functional Interface In Java With Example

An Interface that contains exactly one abstract method is known as functional interface. It can have any number of default and static methods but can contain only one abstract method. Functional Interface is the approach of functional programming in Java. It is also known as SAM interfaces Single Abstract Method Interfaces.

Lambda expressions

can be used to represent the instance of a functional interface.

Rules for a functional interface

  1. A functional interface must have exactly one abstract method.
  2. A functional interface can have any number of default, static methods
  3. No need to declare the abstract keyword as by default the method defined inside the interface is abstract only.

Example of functional interface with lambda expression

/*@FunctionalInterface*/ //It is optional
    public interface MultipleInterface {
        public int multiple(int x,int y);
    }
    
    public class Calculate{
        public static void main (String[] args) {
        //with lambda
        MultipleInterface m = (x, y) -> {
            return x * y;
        };
    
        int multipleVal =   m.multiple(10,30);
        System.out.println( "Multiple Value is "+multipleVal);
        }
    }
    
    Output:
        Multiple Value is 300

@FunctionalInterface Annotation

@FunctionalInterface annotation is optional but it is used to ensure that the functional interface can’t have more than one abstract method. If you add more than one abstract methods, an "Unexpected @FunctionalInterface annotation" message you can get. It is not mandatory to use this annotation.

Example of functional interface with @FunctionalInterface annotation

//It is optional
@FunctionalInterface
interface Area {
	int calculateArea(int x);
}

class Square {
  public static void main (String[] args) {
	//with lambda
    Area a = (x) -> {			
        return x * x;
    };

    int areaVal =   a.calculateArea(20);
    System.out.println( "Area of Square is: "+areaVal);
  }
}

Output:
    Area of Square is: 400

Types of functional interfaces

There are four types of functional interfaces.
  1. Consumer -> Bi-Consumer  details..
  2. Predicate -> Bi-Predicate     details..
  3. Function -> Bi-Function, Unary Operator, Binary Operator  details..
  4. Supplier  details..

1. Consumer

The consumer interface of the functional interface accepts only one single argument without any return value. The consumer interface has no return value. It contains an abstract accept() and a default andThen() method. It can be used as the assignment target for a lambda expression or method reference. details..

Consumer Interface Methods.
  1. void accept(T t)
  2. The accept() method takes as input the type T and returns no value. This is the single abstract method of Consumer. It accepts a single generic argument of type T and returns nothing (i.e. void). This is the method that's implemented by a lambda expression or method reference. details..
  3. andThen(Consumer after)
  4. - The andThen() method is a default method. The method accepts a Consumer and returns another Consumer. details..

Example of Consumer Interface

import java.util.function.Consumer;
public class ConsumerInterfaceExample{

    static void welcomeGreeting (String name){
        System.out.println( "Welcome "+name);
    }
    static void showAge (int age){
        System.out.println( "Your age is "+age);
    }
    static void showSalary (int sal){
        System.out.println( "Your salary is "+sal);
    }

    public static void main(String[] args) {
        //method reference
        Consumer<String> consumer1 = 
            ConsumerInterfaceExample :: welcomeGreeting; 
            // Calling Consumer method
            consumer1.accept("Tejas");
         
        //method reference
        Consumer<Integer> consumer2 =
            ConsumerInterfaceExample :: showAge;
            // Calling Consumer method
            consumer2.accept(30);   

        //method reference
        Consumer<Integer> consumer3 = 
            ConsumerInterfaceExample :: showSalary;
            // Calling Consumer method
            consumer3.accept(20000);     
    }
}

Output:
    Welcome Tejas
    Your age is 30
    Your salary is 20000

Bi-Consumer

The different between Consumer and Bi-Consumer is Consumer takes only one single argument, but Bi-Consumer interface takes two arguments. Both, Consumer and Bi-Consumer have no return value. It is used in iterating through the entries of the map.

BiConsumer<String,String> foo = 
    (a, b) -> System.out.println( a + b );

2. Predicate

Predicate accepts an argument and returns a boolean value. Predicate functional interface in Java is a type of function that accepts a single argument and returns a boolean (True/ False). It provides the functionality of filtering, it filters a stream components on the base of a provided predicate. details..

Predicate Interface Methods.
  1. boolean test(T t)
  2. The Predicate test() method returns true if the input argument matches the predicate, otherwise false.

    Example of Predicate test method

    public static void main (String[] args) {  
      Predicate<Integer> pr = a -> (a > 10);
    
      // Calling Predicate method  
      System.out.println(pr.test(20));       
    }
    
    Output:
    true 
    

  3. static Predicate isEqual(Object targetRef)
  4. The Predicate isEqual() method is a static method of the Predicate interface that is used to test the equality of two objects. The object can be a string, integer, or a class object.

    Example of Predicate isEqual method

     public static void main (String[] args){  
      Predicate<String> pr = 
        Predicate.isEqual( "MyAllText" );
    
        // Calling Predicate method  
        System.out.println(
            pr.test( "AllText" )
        ); 
        // Calling Predicate method  
        System.out.println(
            pr.test( "MyAllText" )
        );
        // Calling Predicate method  
        System.out.println(
            pr.test( "MyAll" )
        );   
    
      }
    } 
    
    Output:
        false
        true
        false
    

  5. default Predicate and(Predicate other)
  6. The Predicate and() method is used to compose two expression(lambda) that represents a short-circuiting logical AND of this predicate. It can be uses to perform logical operations by combining two lambda expressions. See the example below. Here, we used and() method to check whether a number lies between two numeric range or not.

    Example of Predicate and method

    public static void main(String[] args) {   
      Predicate<Integer> pr1 = 
        x -> (x > 20);
    
      Predicate<Integer> pr2 = 
        x -> (x < 80);
    
      // Calling Predicate method  
      System.out.println(
        pr1.and(pr2).test(100)
      ); 
      // Calling Predicate method  
      System.out.println(
        pr1.and(pr2).test(50)
      ); 
      // Calling Predicate method  
      System.out.println(
        pr1.and(pr2).test(10)
      );
    }
    
    Output:
        false
        true
        false
    

  7. default Predicate negate()
  8. The Predicate negate() method allows invert the result of a Predicate. It returns a predicate that represents the logical negation of this predicate.

    Example of Predicate negate method

    public static void main( String[] args) {
      Predicate<String> startsWithCharJ = 
        s -> s.startsWith("H");
      Predicate<String> hasLengthOfInt5 = 
        s -> s.length() == 5;
    
      // Calling without negate method 
      System.out.println(
        startsWithCharJ.test( "Horse" )
      ); 
      // Calling without negate method 
      System.out.println(
        hasLengthOfInt5
        .test( "India" )
      ); 
    
      Predicate<String> negateStartsWithCharJ = 
        startsWithCharJ.negate();
      Predicate<String> negatehasLengthOfInt5 = 
        hasLengthOfInt5.negate();
    
      // Calling after negate predicate 
      System.out.println(
         negateStartsWithCharJ
        .test( "Horse" )
      ); 
    
      // Calling after negate predicate 
      System.out.println(
         negatehasLengthOfInt5
        .test( "India" )
      ); 
    
    } 
    
    Output:
        true
        true
        false
        false
    
    

  9. or(Predicate other)
  10. The Predicate or() method works similarly to and(), but it returns true if either of the any Predicates return true.

    Example of Predicate or method

    public static void main (String[] args) { 
      Predicate<String> startsWithCharH = 
        s -> s.startsWith("H");
      Predicate<String> hasLengthOfInt5 = 
        s -> s.length() == 5;
    
      Predicate<String> startsWithCharHOrHasLengthOf5 = 
        startsWithCharH.or(hasLengthOfInt5);
    
      System.out.println( 
        startsWithCharHOrHasLengthOf5
        .test( "Hero" )
      ); 
    
      System.out.println(
        startsWithCharHOrHasLengthOf5
        .test( "India" )
      ); 
    
      System.out.println(
        startsWithCharHOrHasLengthOf5
        .test( "Method" )
      );
    } 
    
    Output:
        true
        true
        false
    
    

    Bi-Predicate

    Bi-Predicate is also an extension of the Predicate functional interface, which, instead of one, takes two arguments, does some processing, and returns the boolean value.

3. Function

The function type functional interface receives a single argument, processes it, and returns a value. Functional interface is taking the key from the user as input and searching for the value in the map for the given key. details..

public static void main (String[] args) {  
  private static HashMap<Integer, String> Employee = 
            new HashMap<>();
  Function<Integer, String> addFunc = (Integer ID)-> {
    if(Employee.containsKey(ID)) {
        return Employee.get(ID);
    }else{
        return "Invalid ID";
    }
  };
  // Returns the Employee object if present in the hashmap or return Invalid Id message        
  System.out.println( addFunc.apply( 500 )); 
};

Bi Function

Bi-function is just like a function, it takes two arguments. Two arguments are must in Bi-function. Just like a function it also returns a value.

4. Supplier

The Supplier functional interface is also a type of functional interface that does not take any input or argument and returns a single output. The Supplier interface takes only one generic type, the type of data it is going to return. get() is the abstract method of the Supplier. details..

public static void main (String[] args) { 
    Supplier<String> supp = () -> "Hello World";
    System.out.println( supp.get() );        
};

Output:
    Hello World